//
//  BaseScrollView.m
//  66
//
//  Created by ioszhe on 15/12/10.
//  Copyright © 2015年 66. All rights reserved.
//

#import "BaseScrollView.h"

#define KeyPathContentOffset @"contentOffset"

@implementation UIScrollView (scroll)

- (void)dealloc{
    self.isMultiSubScroll = NO;
}

- (void)gk_scrollToBottomAnimated:(BOOL)animated{
    CGPoint off = self.contentOffset;
    off.y = self.contentSize.height - self.bounds.size.height + self.contentInset.bottom;
    off.y = MAX(0, off.y);
    [self setContentOffset:off animated:animated];
}

- (void)gk_scrollToTopAnimated:(BOOL)animated{
    CGPoint off = self.contentOffset;
    if (@available(iOS 11.0, *)) {
        off.y = 0 - self.adjustedContentInset.top;
    } else {
        off.y = 0 - self.contentInset.top;
    }
    [self setContentOffset:off animated:animated];
}


- (void)setLastOffset:(CGPoint)lastOffset{
    [self objc_setAssociatedObject:@"lastOffset" value:[NSValue valueWithCGPoint:lastOffset] policy:OBJC_ASSOCIATION_RETAIN_NONATOMIC];
}

- (CGPoint)lastOffset{
    NSValue *tmp = [self objc_getAssociatedObject:@"lastOffset"];
    return [tmp CGPointValue];
}

- (void)setIgnoreScroll:(BOOL)ignoreScroll{
    [self objc_setAssociatedObject:@"ignoreScroll" value:[NSNumber numberWithBool:ignoreScroll] policy:OBJC_ASSOCIATION_RETAIN_NONATOMIC];
    if (ignoreScroll) {
        self.lastOffset = self.contentOffset;
    }
}

- (BOOL)ignoreScroll{
    NSNumber *tmp = [self objc_getAssociatedObject:@"ignoreScroll"];
    return [tmp boolValue];
}


- (BOOL)isMultiSubScroll{
    NSNumber *tmp = [self objc_getAssociatedObject:@"isMultiSubScroll"];
    return [tmp boolValue];
}

- (void)setIsMultiSubScroll:(BOOL)isMultiSubScroll{
    BOOL _isMultiSubScroll = self.isMultiSubScroll;
    if (_isMultiSubScroll == isMultiSubScroll) {
        return;
    }
    
    [self objc_setAssociatedObject:@"isMultiSubScroll" value:[NSNumber numberWithBool:isMultiSubScroll] policy:OBJC_ASSOCIATION_RETAIN_NONATOMIC];
    
    if (isMultiSubScroll) {
        NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
        [self addObserver:self forKeyPath:KeyPathContentOffset options:options context:nil];
    }else{
        [self removeObserver:self forKeyPath:KeyPathContentOffset];
    }
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    // 遇到这些情况就直接返回
    if (!self.userInteractionEnabled) return;
    
    // 这个就算看不见也需要处理
    if ([keyPath isEqualToString:KeyPathContentOffset]) {
        UIScrollView *scrollView = self;
        CGPoint offset = self.contentOffset;
        CGPoint lastOffset = self.lastOffset;
        if (scrollView.ignoreScroll) {
            BOOL isUp = offset.y > lastOffset.y;
            CGFloat offsetY = offset.y + scrollView.contentInset.top;
            if (isUp && offsetY < 0) {
                
            }else {
                offset = lastOffset;
                if (scrollView.contentOffset.y != offset.y) {
                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                        scrollView.contentOffset = offset;
                    });
                }
                return;
            }
        }
        scrollView.lastOffset = offset;
    }
}


@end



@interface BaseScrollView(){
    
}

@end

@implementation BaseScrollView

- (void)dealloc{
    self.isMultiContentScroll = NO;
    self.customAction = nil;
}

- (instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        [self initViews];
    }
    return self;
}

- (BOOL)touchesShouldCancelInContentView:(UIView *)view{
    return YES;
}

- (void)setSubScrollView:(UIScrollView *)subScrollView{
    _subScrollView = subScrollView;
    _subScrollView.isMultiSubScroll = YES;
}

- (void)setIsMultiContentScroll:(BOOL)isMultiContentScroll{
    if (_isMultiContentScroll == isMultiContentScroll) {
        return;
    }
    _isMultiContentScroll = isMultiContentScroll;
    
    if (_isMultiContentScroll) {
        NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
        [self addObserver:self forKeyPath:KeyPathContentOffset options:options context:nil];
    }else{
        [self removeObserver:self forKeyPath:KeyPathContentOffset];
    }
    self.scrollsToTop = !_isMultiContentScroll;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    // 遇到这些情况就直接返回
    if (!self.userInteractionEnabled) return;
    if (self.ignoreScroll) {
        return;
    }
    // 这个就算看不见也需要处理
    if ([keyPath isEqualToString:KeyPathContentOffset]) {
        UIScrollView *scrollView = self;
        CGPoint offset = scrollView.contentOffset;
        CGPoint lastOffset = self.lastOffset;
        BOOL isUp = offset.y >= lastOffset.y;
        BOOL ignoreScroll = NO;
        
        UIScrollView *subScrollView = _subScrollView;
        if (offset.y >= _limitOffsetY) {
            offset.y = _limitOffsetY;
            ignoreScroll = YES;
            if (isUp) {
                subScrollView.ignoreScroll = NO;
            }else {
                subScrollView.ignoreScroll = YES;
            }
        }else if (offset.y <=0){
            offset.y = 0;
            ignoreScroll = YES;
            if (isUp) {
                subScrollView.ignoreScroll = YES;
            }else {
                subScrollView.ignoreScroll = NO;
            }
        }else {
            CGFloat tmp = subScrollView.contentOffset.y + subScrollView.contentInset.top;
            if (!isUp && tmp >= 0) {
                ignoreScroll = YES;
            }else {
                ignoreScroll = NO;
            }
            
            if (ignoreScroll) {
                offset = lastOffset;
                subScrollView.ignoreScroll = NO;
            }else {
                subScrollView.ignoreScroll = YES;
            }
            
        }

        //使用animation 会停止滚动
        if (ignoreScroll && fabs(scrollView.contentOffset.y - offset.y)>0.01) {
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                scrollView.contentOffset = offset;
            });
        }

        self.lastOffset = offset;
    }
}

/**
 同时识别多个手势

 @param gestureRecognizer gestureRecognizer description
 @param otherGestureRecognizer otherGestureRecognizer description
 @return return value description
 */
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return _isMultiContentScroll;
}

@end
